package com.lsh.ofc.core.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.lsh.base.common.exception.BusinessException;
import com.lsh.ofc.core.constant.Constants;
import com.lsh.ofc.core.entity.OfcOrderDetail;
import com.lsh.ofc.core.entity.OfcOrderHead;
import com.lsh.ofc.core.entity.OfcSoDetail;
import com.lsh.ofc.core.entity.OfcSoHead;
import com.lsh.ofc.core.enums.DistributionType;
import com.lsh.ofc.core.enums.SkuDefine;
import com.lsh.ofc.core.exception.EC;
import com.lsh.ofc.core.model.SoMergeOrderInfoBO;
import com.lsh.ofc.core.service.OfcCustomerService;
import com.lsh.ofc.core.service.OfcOrderService;
import com.lsh.ofc.core.service.OfcSoMergeNotifyOtherSystemService;
import com.lsh.ofc.core.service.OfcSoService;
import com.lsh.ofc.proxy.model.CreatePmsSoReqDetail;
import com.lsh.ofc.proxy.service.OmsServiceProxy;
import com.lsh.ofc.proxy.service.PmsServiceProxy;
import com.lsh.ofc.proxy.service.TmsServiceProxy;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.message.BasicNameValuePair;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;

/**
 * Project Name: OfcSoMergeNotifyOtherSystemServiceImpl
 * 北京链商电子商务有限公司
 *
 * @author wangliutao
 * Date: 19/3/4
 * Package Name: com.lsh.ofc.core.service.impl
 * Description:
 */
@Slf4j
@Service
public class OfcSoMergeNotifyOtherSystemServiceImpl implements OfcSoMergeNotifyOtherSystemService {

    private final OmsServiceProxy omsServiceProxy;

    private final TmsServiceProxy tmsServiceProxy;

    private final OfcOrderService ofcOrderService;

    private final OfcCustomerService ofcCustomerService;

    private final OfcSoService ofcSoService;

    private final PmsServiceProxy pmsServiceProxy;

    public OfcSoMergeNotifyOtherSystemServiceImpl(OmsServiceProxy omsServiceProxy, TmsServiceProxy tmsServiceProxy, OfcOrderService ofcOrderService, OfcCustomerService ofcCustomerService, PmsServiceProxy pmsServiceProxy, OfcSoService ofcSoService) {
        this.omsServiceProxy = omsServiceProxy;
        this.tmsServiceProxy = tmsServiceProxy;
        this.ofcOrderService = ofcOrderService;
        this.ofcCustomerService = ofcCustomerService;
        this.pmsServiceProxy = pmsServiceProxy;
        this.ofcSoService = ofcSoService;
    }

    /**
     * 构建请求PMS的detail
     *
     * @param so                 so
     * @param pmsSoReqDetailList list
     */
    @Override
    public void buildPmsSoDetails(OfcSoHead so, List<CreatePmsSoReqDetail> pmsSoReqDetailList) {
        for (OfcSoDetail detail : so.getDetails()) {
            CreatePmsSoReqDetail pmsSoReqDetail = new CreatePmsSoReqDetail();
            pmsSoReqDetail.setSoBillCode(detail.getSoBillCode());
            pmsSoReqDetail.setItemNo(detail.getItemNo());
            pmsSoReqDetail.setSupplierDc(so.getSupplierDc());
            pmsSoReqDetail.setSupplierOrg(so.getSupplierOrg());
            pmsSoReqDetail.setSkuCode(detail.getSkuCode());
            pmsSoReqDetail.setGoodsCode(detail.getGoodsCode());
            pmsSoReqDetail.setGoodsName(detail.getGoodsName());
            pmsSoReqDetail.setGoodsMoney(detail.getGoodsAmount());
            pmsSoReqDetail.setCode(detail.getSkuSupplyCode());
            pmsSoReqDetail.setPrice(detail.getGoodsPrice());
            pmsSoReqDetail.setRealQty(detail.getSkuSupplyQty());
            pmsSoReqDetail.setExt(detail.getExt());
            pmsSoReqDetail.setSaleUnit(detail.getGoodsSaleUnit());

            String ext = detail.getExt();
            JSONObject extJson = JSON.parseObject(ext);
            pmsSoReqDetail.setSkuDefine(extJson.getString(Constants.ORDER_D_SKU_DEFINE));

            pmsSoReqDetailList.add(pmsSoReqDetail);
        }
    }

    /**
     * 构建请求TMS的detail
     *
     * @param so    so
     * @param items 详情
     */
    @Override
    public void buildTmsSoDetails(OfcSoHead so, JSONArray items) {
        for (OfcSoDetail detail : so.getDetails()) {
            JSONObject item = new JSONObject();
            Integer isWeighingGoods = JSONObject.parseObject(detail.getExt()).getInteger("is_weighing_goods");
            item.put("supplier_id", so.getSupplierId());
            item.put("supplier_org", so.getSupplierOrg());
            item.put("supplier_dc", so.getSupplierDc());
            item.put("item_id", detail.getSkuCode().toString());
            item.put("name", detail.getGoodsName());
            item.put("item_qty", detail.getSkuOrderQty().toString());
            item.put("item_supply_code", detail.getSkuSupplyCode());
            item.put("s_qty", detail.getSkuSupplyQty().toString());
            item.put("sale_unit", detail.getGoodsSaleUnit().toString());
            item.put("is_weighing_goods", isWeighingGoods);

            JSONObject ext = JSON.parseObject(detail.getExt());
            item.put("pack_unit", ext.getString("pack_unit"));
            item.put("pack_name", ext.getString("pack_name"));

            items.add(item);
        }
    }

    /**
     * 订单下发TMS
     *
     * @param items     详情
     * @param orderInfo 订单信息
     * @return boolean
     */
    @Override
    public boolean notifyTms(JSONArray items, SoMergeOrderInfoBO orderInfo) {

        OfcOrderHead param = new OfcOrderHead();
        param.setOrderCode(orderInfo.getOrderCode());
        OfcOrderHead bill = this.ofcOrderService.findList(param, true).get(0);
        String mpCustCode = StringUtils.collectionToDelimitedString(orderInfo.getMpCustCodes(), ",");
        List<BasicNameValuePair> pairs = new ArrayList<>(15);

        pairs.add(new BasicNameValuePair("warehouse_id", bill.getWarehouseCode()));
        pairs.add(new BasicNameValuePair("other_id", orderInfo.getOrderCode().toString()));
        pairs.add(new BasicNameValuePair("address_info", bill.getAddressInfo()));
        pairs.add(new BasicNameValuePair("money", bill.getOrderAmount().toString()));
        pairs.add(new BasicNameValuePair("ordered_at", bill.getOrderTime().toString()));
        pairs.add(new BasicNameValuePair("source_system", JSON.toJSONString(orderInfo.getSourceSystem())));
        pairs.add(new BasicNameValuePair("items", JSON.toJSONString(items)));
        pairs.add(new BasicNameValuePair("type", orderInfo.getOrderType().toString()));
        pairs.add(new BasicNameValuePair("so_user_id", mpCustCode));
        pairs.add(new BasicNameValuePair("remarks", ""));
        pairs.add(new BasicNameValuePair("ext", ""));

        boolean ret = this.tmsServiceProxy.addTmsTask(pairs, orderInfo.getVenderId());
        if (!ret) {
            throw EC.ERROR.exception("下发TMS失败！订单号=" + orderInfo.getOrderCode());
        }

        return true;
    }

    /**
     * 统计箱数
     *
     * @param details 详情
     * @return 返回值
     * @throws BusinessException 异常
     */
    private BigDecimal sumBoxQty(List<OfcOrderDetail> details) throws BusinessException {
        if (CollectionUtils.isEmpty(details)) {
            return BigDecimal.ZERO;
        }
        BigDecimal eaQty = BigDecimal.ZERO;
        BigDecimal boxQty = BigDecimal.ZERO;
        for (OfcOrderDetail detail : details) {
            if (detail == null) {
                continue;
            }
            Long skuCode = detail.getSkuCode();
            Integer define = JSON.parseObject(detail.getExt()).getInteger(Constants.ORDER_D_SKU_DEFINE);
            if (SkuDefine.EA.getCode().equals(define)) {
                if (detail.getGoodsSaleUnit().compareTo(BigDecimal.ONE) == 0) {
                    eaQty = eaQty.add(detail.getGoodsQty());
                } else {
                    boxQty = boxQty.add(detail.getGoodsQty());
                }
            } else if (SkuDefine.BOX.getCode().equals(define)) {
                log.warn("sku_define=2, sku_code=" + skuCode);
                boxQty = boxQty.add(detail.getGoodsQty());
            } else if (SkuDefine.KG.getCode().equals(define)) {
                log.warn("sku_define=3, sku_code=" + skuCode);
                if (detail.getGoodsSaleUnit().compareTo(BigDecimal.ONE) == 0) {
                    eaQty = eaQty.add(detail.getGoodsQty());
                } else {
                    boxQty = boxQty.add(detail.getGoodsQty());
                }
            } else {
                throw EC.ERROR.exception("sku_define is error! define=" + define + ", sku_code=" + skuCode);
            }
        }

        log.info("Order[" + details.get(0).getOrderCode() + "] details unit: ea=" + eaQty + ", box=" + boxQty);
        return boxQty.add(eaQty.divide(BigDecimal.valueOf(20), 2, BigDecimal.ROUND_HALF_UP));
    }

    /**
     * 订单下发PMS
     *
     * @param orderInfo          订单信息
     * @param pmsSoReqDetailList 详情
     * @param stoExt             ext
     * @return boolean
     */
    @Override
    public boolean notifyPms(SoMergeOrderInfoBO orderInfo, List pmsSoReqDetailList, String stoExt) {
        List<BasicNameValuePair> pairList = new ArrayList<>(12);
        OfcOrderHead orderFilter = new OfcOrderHead();
        orderFilter.setOrderCode(orderInfo.getOrderCode());
        OfcOrderHead bill = this.ofcOrderService.findList(orderFilter, true).get(0);
        pairList.add(new BasicNameValuePair("order_id", String.valueOf(bill.getOrderCode())));
        pairList.add(new BasicNameValuePair("other_id", StringUtils.collectionToDelimitedString(orderInfo.getSoBillCodes(), ",")));
        pairList.add(new BasicNameValuePair("address_id", String.valueOf(bill.getAddressCode())));
        pairList.add(new BasicNameValuePair("warehouse_id", bill.getWarehouseCode()));
        pairList.add(new BasicNameValuePair("so_bill_code", StringUtils.collectionToDelimitedString(orderInfo.getSoBillCodes(), ",")));
        pairList.add(new BasicNameValuePair("pre_warehouse_id", bill.getPreWarehouseCode()));
        pairList.add(new BasicNameValuePair("supplier_org", StringUtils.collectionToDelimitedString(orderInfo.getSoSupplyOrg(), ",")));
        // TODO sto 与 so 对应关系
        pairList.add(new BasicNameValuePair("ext", stoExt));
        pairList.add(new BasicNameValuePair("items", JSON.toJSONString(pmsSoReqDetailList)));

        if (bill.getOrderDistributionType().equals(DistributionType.ORDER_SO.getCode())) {
            pairList.add(new BasicNameValuePair("so_code", StringUtils.collectionToDelimitedString(orderInfo.getSoCodes(), ",")));
        } else {
            pairList.add(new BasicNameValuePair("sto_code", StringUtils.collectionToDelimitedString(orderInfo.getSoCodes(), ",")));
        }

        boolean ret = pmsServiceProxy.pushOrderSo(pairList, bill.getOrderDistributionType());
        if (!ret) {
            throw EC.ERROR.exception("下发PMS失败！订单号=" + orderInfo.getOrderCode());
        }
        log.info("【{}】 so merge 下发pms成功", orderInfo.getOrderCode());
        return true;
    }

    /**
     * 通知OMS，修改订单状态等信息
     *
     * @param orderInfo 订单信息
     */
    @Override
    public void notifyOms(SoMergeOrderInfoBO orderInfo) {
        String mpCustCode = StringUtils.collectionToDelimitedString(orderInfo.getMpCustCodes(), ",");

        BigDecimal totalSkuOrderQty = orderInfo.getTotalSkuOrderQty();
        BigDecimal totalSkuSupplyQty = orderInfo.getTotalSkuSupplyQty();
        int lack;
        if (totalSkuSupplyQty == null || totalSkuSupplyQty.compareTo(BigDecimal.ZERO) <= 0) {
            //全部缺交
            lack = 1;
        } else if (totalSkuSupplyQty.compareTo(totalSkuOrderQty) < 0) {
            //部分缺交
            lack = 2;
        } else {
            lack = 0;
        }


        OfcSoHead soHead = getSoHead(orderInfo);
        JSONObject headJson = JSON.parseObject(soHead.getExt());
        Integer saleModel = headJson.getInteger("saleModel");
        Integer deliveryType = headJson.getInteger("deliveryType");

        // 因为进销存，wms发货都是按照so_bill_code发货，所以方便客服在各个系统查询。回传oms，从socodes改为sobillcodes
        boolean ret = this.omsServiceProxy.updateOrderStatus(orderInfo.getOrderCode(), 22, lack, orderInfo.getMixtureSoCodes(), orderInfo.getWarehouseCodes(), mpCustCode, deliveryType, saleModel);
        if (!ret) {
            throw EC.ERROR.exception("更新OMS订单状态失败！订单号=" + orderInfo.getOrderCode());
        }
    }

    private OfcSoHead getSoHead(SoMergeOrderInfoBO orderInfo) {

        OfcSoHead filter = new OfcSoHead();
        filter.setOrderCode(orderInfo.getOrderCode());
        List<OfcSoHead> soHeads = ofcSoService.findList(filter, false);

        if (!CollectionUtils.isEmpty(soHeads)) {
            return soHeads.get(0);
        }

        return null;
    }

}
